#include "Director.h"

SINGLETON_DEFINE(Director);

Director::Director(void)
{
	CurrentScene = PreviousScene = NULL;
}

Director::~Director(void)
{
	DELETE_PTR(Director_Instance);
	DELETE_PTR(CurrentScene);
	DELETE_PTR(PreviousScene);
}
void Director::Init(int argc, char **argv, const char* title)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);

	// Resize the window to 800x600 and place it in the middle of the screen
	glutInitWindowPosition(glutGet(GLUT_SCREEN_HEIGHT) / 2, glutGet(GLUT_SCREEN_WIDTH) / 2);
	glutInitWindowSize(800,600);

	glutCreateWindow(title);

	glutIdleFunc			(SceneIdle);
	glutDisplayFunc			(SceneDisplay);
	glutKeyboardFunc		(SceneKeyboardDown);
	glutKeyboardUpFunc		(SceneKeyboardUp);
	glutSpecialFunc			(SceneSpecialDown);
	glutSpecialUpFunc		(SceneSpecialUp);
	glutMouseFunc			(SceneMouse);
	glutMotionFunc			(SceneMotion);
	glutPassiveMotionFunc	(ScenePassiveMotion);

	glutMainLoop();
}

void Director::SetWindowSize(int width, int height)
{
	glutReshapeWindow(width,height);
}
void Director::AddScene(string name, Scene* scene, bool bRunScene)
{
	if(!SceneList[name])			// if there is not a scene with the same name
		SceneList[name] = scene;

	if(bRunScene) ChangeScene(name);
}

void Director::ChangeScene(string name)
{
	// Check if requested scene is not in the list
	ErrorMsg( SceneList.find(name) == SceneList.end(), "Scene not found!");

	if(CurrentScene != NULL)			// if there is a Scene running
	{
		PreviousScene = CurrentScene;	// mark the current Scene as previous
		PreviousScene->Drop();			// clear up its resources 
		PreviousScene->setResourceReady(false);
	}

	CurrentScene = SceneList[name];		// retrieve the requested Scene from the SceneList

	if(!CurrentScene->getResourceReady())	// if the Scene has not loaded it's resources
	{
		CurrentScene->Load();			// then let it load its resources
		CurrentScene->setResourceReady(true);
	}
}

void SceneIdle(void)
{
	Scene* CurrentScene = Director::getInstance()->getCurrentScene();
	if(CurrentScene != NULL)
		CurrentScene->Idle();
}

void SceneDisplay(void)
{
	Scene* CurrentScene = Director::getInstance()->getCurrentScene();
	if(CurrentScene != NULL)
		CurrentScene->Display();
}

void SceneKeyboardDown(unsigned char key, int x, int y)
{
	Scene* CurrentScene = Director::getInstance()->getCurrentScene();
	if(CurrentScene != NULL)
		CurrentScene->KeyboardDown(key, x, y);
}

void SceneKeyboardUp(unsigned char key, int x, int y)
{
	Scene* CurrentScene = Director::getInstance()->getCurrentScene();
	if(CurrentScene != NULL)
		CurrentScene->KeyboardUp(key, x, y);
}

void SceneSpecialDown(int key, int x, int y)
{
	Scene* CurrentScene = Director::getInstance()->getCurrentScene();
	if(CurrentScene != NULL)
		CurrentScene->SpecialDown(key, x, y);
}

void SceneSpecialUp(int key, int x, int y)
{
	Scene* CurrentScene = Director::getInstance()->getCurrentScene();
	if(CurrentScene != NULL)
		CurrentScene->SpecialUp(key, x, y);
}

void SceneMouse(int button, int state, int x, int y)
{
	Scene* CurrentScene = Director::getInstance()->getCurrentScene();
	if(CurrentScene != NULL)
		CurrentScene->Mouse(button, state, x, y);
}

void SceneMotion(int x, int y)
{
	Scene* CurrentScene = Director::getInstance()->getCurrentScene();
	if(CurrentScene != NULL)
		CurrentScene->Motion(x, y);
}

void ScenePassiveMotion(int x, int y)
{
	Scene* CurrentScene = Director::getInstance()->getCurrentScene();
	if(CurrentScene != NULL)
		CurrentScene->PassiveMotion(x, y);
}
